<?php
// 接口-出库单接口
namespace interface\v1;

use verify;

class outStockClass extends index
{
	private const        page        = 'outStockOther';
	private const        table       = 'inventory';
	private const        tableMx     = 'inventory_detail';
	private const        tableRecord = 'inventory_record';
	private const        tableTarget = 'kehu';
	private const        title       = '出库单';
	private const        workFlow    = ['草稿', '待出库', '部分出库', '已出库'];
	private const        source      = ['盘点单', '生产出库', '领退料', '销售退货', '采购收货'];

	public function search()
	{
		$this->code         = 1;
		$this->resp['data'] = [
			'orderNo'     => '单据条码',
			'warehouseId' => find(['table' => 'warehouse', 'field' => 'id as value, name as text', 'where' => " coid = '" . self::$coid . "' AND state = '启用' "])['array'],
			'state'       => [
				'待出库', '部分出库', '已出库',
			],
		];
	}


	/**
	 * 列表
	 *
	 * @return void
	 */
	public function list()
	{
		//获取查询结果
		$where = search([
			"="    => [
				'warehouseId' => $this->post('warehouseId'),
				'coid'        => self::$coid,
				// 'type'        => '其他出库',
			],
			'like' => [
				'orderNo' => $this->post('orderNo'),
			],
			"in"   => [
				'state' => $this->post('state') ? (($this->post('state') === '待出库') ? ['待出库', '草稿'] : [$this->post('state')]) : ['待出库', '草稿'],
			],
		]);
		$page  = $this->page(["table" => self::table, "where" => $where, "order" => "time desc"]);
		//数据分析
		$data['result'] = [];
		foreach ($page['array'] as $array) {
			$target           = query(self::tableTarget, " khid = '$array[targetId]' ");
			$result           = find([
				'table'  => self::tableMx,
				'field'  => ' any_value(materialId) as materialId, IFNULL(sum(num), 0) as total ',
				'single' => " orderId = '$array[id]' ",
			]);
			$material         = query('material', " id = '$result[materialId]' ");
			$data['result'][] = [
				"id"       => $array['id'],
				'orderNo'  => $array['orderNo'],
				'type'     => $array['type'],
				'target'   => $target ? $target['companyName'] : '',
				'material' => $material['name'] . '等' . self::lostZero($result['total'], 'numPrecision') . $material['unit'],
				"state"    => $array['state'],
				'time'     => self::formatDate($array['time'], 'Y/m/d'),
			];
		}
		$data['page'] = $page['para'];
		//返回
		$this->code         = 1;
		$this->resp['data'] = $data;
	}


	/**
	 * 选择物料
	 */
	public function material()
	{
		$waid = $this->post('waid');
		if (!$waid) {
			$this->resp['warn'] = '请选择仓库';
		} else {
			$materialId = $this->post('materialId') ? explode(',', $this->post('materialId')) : [];
			$where      = " 1=1 and a.id not in ('" . implode("','", $materialId) . "')";
			$and        = " AND a.coid = '" . self::$coid . "' ";
			$like       = [
				'a.name'    => $this->post('materialName'),
				'a.barcode' => $this->post('code'),
				// 'model'  => $this->post('model'),
			];
			$equal      = [
				'a.state' => '启用',
				// 'a.typeId' => $this->post('type'),
			];
			$where      .= search(["like" => $like, "=" => $equal]) . $and;
			$orderBy    = $this->orderBy([
				"search"  => $this->post('orderBy') ?: null,
				"default" => "创建时间降序",
				"array"   => [
					"a.time"       => ["asc" => "创建时间升序", "desc" => "创建时间降序", "site" => 2],
					"a.updateTime" => ["asc" => "更新时间升序", "desc" => "更新时间降序", "site" => 3],
				],
			]);
			$page       = $this->page([
				"table"   => "material as a",
				"field"   => "a.*",
				"where"   => $where,
				'pageNum' => 50,
				"order"   => $orderBy['orderBy'],
			]);
			$result     = [];
			//获取记录
			foreach ($page['array'] as $array) {
				// 物料编码  物料名称  品牌 规格型号 库存 可用库存 物料id
				$warehouse    = query('warehouse', " id = '$waid'");
				$inventoryNum = inventoryBalanceClass::inventoryNum($array['id'], $waid);
				$result[]     = [
					'materialId'      => $array['id'],
					'name'            => $array['code'] . ' ' . $array['name'] . $array['model'],
					'model'           => $array['model'],
					'barcode' => $array['barcode'],
					'num'             => $inventoryNum,
					'unit'            => $array['unit'],
					'unitOption'      => inventoryBalanceClass::materialUnit($array['id']),
					'availableNum'    => $inventoryNum,
					'warehouseId'     => $waid,
					'warehouseName'   => $warehouse['name'],
				];
			}
			$orderByArr         = [
				'创建时间降序',
				'创建时间升序',
				'更新时间降序',
				'更新时间升序',
			];
			$this->resp['data'] = [
				'result'  => $result,
				'page'    => $page['para'],
				'orderBy' => $orderByArr,
			];
			$this->code         = 1;
		}
	}

	/**
	 * 编辑
	 */
	public function edit(): void
	{
		$detail           = !empty($_POST['detail']) ? json_decode($_POST['detail'], true) : [];
		$id               = $this->post('id') ?: self::getId();
		$mxIdArr          = $this->post('mxId') ?: inStockClass::getArrVal('id', $detail);
		$materialIdArr = $this->post('materialId') ?: inStockClass::getArrVal('materialId', $detail);
		$unitArr          = $this->post('unit') ?: inStockClass::getArrVal('unit', $detail);
		$numArr           = $this->post('num') ?: inStockClass::getArrVal('num', $detail);
		$priceArr         = $this->post('price') ?: inStockClass::getArrVal('price', $detail);
		$mxTextArr        = $this->post('mxText') ?: inStockClass::getArrVal('mxText', $detail);
		$warehouseArr     = $this->post('warehouseId') ?: inStockClass::getArrVal('warehouseId', $detail);

		$field      = [
			'warehouseId' => $this->post('waid'),
			'targetId'    => $this->post('targetId'),
			'orderDate'   => $this->post('orderDate'),
			'text'        => $this->post('text'),
		];
		$annotation = [
			'warehouseId' => '仓库',
			'targetId'    => '客户',
			'orderDate'   => '单据日期',
			'text'        => '备注',
		];
		$rules      = [
			'warehouseId' => 'required',
			'targetId'    => 'required',
			'orderDate'   => 'required|date',
			// 'text'           => 'required',
		];
		// 校验是否符合规则
		$vt     = new verify();
		$result = $vt->setAliases($annotation)->validate($field, $rules)->isOk();
		if ($result === false) {
			$this->resp['warn'] = $vt->getErrs()[0]; // 多个规则提示最前面一条
			goto resp;
		}
		$where = " coid = '" . self::$coid . "' AND id = '$id' ";
		$info  = query(self::table, $where);
		//判断
		if (!$this->power(self::page, "edit")) {
			$this->resp['warn'] = "你没有编辑" . self::title . "的权限";
		} elseif (self::is_null_array($mxIdArr)) {
			$this->resp['warn'] = '请选择出库明细';
		} elseif (self::is_null_array($materialIdArr)) {
			$this->resp['warn'] = '请选择出库明细';
		} elseif (self::is_null_array($numArr)) {
			$this->resp['warn'] = '数量请填写完整';
		} elseif (self::is_null_array($priceArr)) {
			$this->resp['warn'] = '价格请填写完整';
		} elseif (self::is_null_array($unitArr)) {
			$this->resp['warn'] = '请选择主单位';
		} elseif (self::is_null_array($warehouseArr)) {
			$this->resp['warn'] = '请选择出库仓库';
		} elseif (!empty($info['id']) && $info['state'] == '已出库') {
			$this->resp['warn'] = '此出库单已出库，不能修改';
		} else {
			$this->startTrans();
			$isPass = true;//事务通过标志
			if (!$info['id']) {
				$state              = (!empty($this->header['Source']) && strtoupper($this->header['Source']) === 'PDA') ? '待出库' : '草稿';
				$orderNo            = self::generateCode(self::page,[
                    'prefix' => 'QTRK' . date('Ymd'),
                    'table'  => self::table,
                    'field'  => 'orderNo',
                    'where'  => '',
                ],$field);
				$field              = array_merge($field, [
					'id'          => $id,
					'orderNo'     => $orderNo,
					'type'        => '其他出库',
					'subCategory' => '其他出库',
					'classify'    => 0,
					'state'       => $state,
					'coid'        => self::$coid,
					'stid'        => $this->control['stid'],
				]);
				$this->resp['warn'] = static::insert([
					"table" => self::table,
					"field" => $field,
				]);
			} else {
				$this->resp['warn'] = static::update([
					"table" => self::table,
					"field" => $field,
					"where" => $where,
				]);
			}
			//添加或更新报价单明细
			if (is_array($mxIdArr)) {
				foreach ($mxIdArr as $k => $nid) {
					$mx          = query(self::tableMx, "id = '$nid'");
					if (!empty($mx['id'])) {
						//更新
						$warn = static::update([
							"table" => self::tableMx,
							"field" => [
								'materialId'    => $materialIdArr[$k],
								'num'           => $numArr[$k],
								'price'         => $priceArr[$k],
								'unit'          => $unitArr[$k],
								'warehouseId'   => $warehouseArr[$k],
								'money'         => round($numArr[$k] * $priceArr[$k], 2),
								'text'          => $mxTextArr[$k],
							],
							"where" => " id = '$nid'",
						]);
					} else {
						//新增
						$warn = static::insert([
							"table" => self::tableMx,
							"field" => [
								'id'            => $nid,
								'coid'          => self::$coid,
								'orderId'       => $id,
								'materialId'    => $materialIdArr[$k],
								'num'           => $numArr[$k],
								'price'         => $priceArr[$k],
								'unit'          => $unitArr[$k],
								'warehouseId'   => $warehouseArr[$k],
								'money'         => round($numArr[$k] * $priceArr[$k], 2),
								'text'          => $mxTextArr[$k],
							],
						]);
					}
					if (!in_array($warn, ['新增成功', '更新成功'])) {
						$isPass             = false;
						$this->resp['warn'] = $warn;
						break;
					}
				}
			}
			if (in_array($this->resp['warn'], ["新增成功", "更新成功"]) && $isPass) {
				$this->commitTrans();
				//是否是处理不良
				if ($this->resp['warn'] == '新增成功' && $this->post('qidMxId')) {
					update(array('table' => 'quality_order_reason', 'field' => array('state' => '已处理', 'dealDate' => $this->date, 'dealId' => self::$stid), 'where' => "id ='" . $this->post('qidMxId') . "' and state = '待处理' and coid = '" . self::$coid . "'"));
				}
				delete(['table' => self::tableMx, 'where' => " id not in ('" . implode("','", $mxIdArr) . "') and orderId = '$id'"]);
				//添加日志
				$type = mb_substr($this->resp['warn'], 0, 2, 'utf-8');
				$text = $this->control['name'] . $type . "了" . self::title . " id：【" . $id . '】';
				$this->logText(["type" => self::page, "text" => $text]);
				//返回
				$this->code         = 1;
				$this->resp['data'] = $id;
			} else {
				$this->rollback();
			}
		}

		resp:
	}

	/**
	 * 提交
	 */
	public function commit()
	{
		$id    = $this->post('id');
		$info  = query(self::table, " coid = '" . self::$coid . "' AND id = '$id'");
		$field = [
			'state' => '待出库',
		];
		if (!$this->power(self::page, 'edit')) {
			$this->resp['warn'] = '你还没有编辑权限';
		} elseif (empty($info['id'])) {
			$this->resp['warn'] = '未找到此其他出库单';
		} elseif ($info['state'] != '草稿') {
			$this->resp['warn'] = '此报价单不是草稿状态，不能提交';
		} else {
			$this->resp['warn'] = update(array(
				"table" => self::table,
				"field" => $field,
				"where" => "id = '$info[id]'",
			));
			if (in_array($this->resp['warn'], ["新增成功", "更新成功"])) {
				auditingFollow([
					"type"   => "其他出库单",
					"typeId" => $info['id'],
					"text"   => "【{$this->control['name']}】提交",
				]);
				//添加日志
				$type = mb_substr($this->resp['warn'], 0, 2, 'utf-8');
				$text = $this->control['name'] . $type . "了" . self::title . "id：【" . $id . '】';
				$this->logText(["type" => self::page, "text" => $text]);
				$this->code = 1;
			}
		}
		resp:
	}

	/**
	 * 确认出库
	 */
	public function confirmEdit()
	{
		$id    = $this->post('id');
		$info  = query(self::table, " coid = '" . self::$coid . "' AND id = '$id'");
		$field = [
			'state' => '已出库',
		];
		if (!$this->power(self::page, 'confirm')) {
			$this->resp['warn'] = '你还没有确认权限';
		} elseif (empty($info['id'])) {
			$this->resp['warn'] = '未找到此其他出库单';
		} elseif ($info['state'] == '已出库') {
			$this->resp['warn'] = '此申请是已出库状态，不能确认';
		} else {
			$this->startTrans();
			$isPass             = true; // 事务通过标志
			$this->resp['warn'] = update([
				"table" => self::table,
				"field" => $field,
				"where" => "id = '$info[id]'",
			]);
			if (in_array($this->resp['warn'], ["新增成功", "更新成功"]) && $isPass === true) {
				$details = find([
					'table' => self::tableMx,
					'where' => " orderId = '{$info['id']}'",
				]);
				foreach ($details['array'] as $value) {
					// 转换主单位
					$mainUnitNum = inventoryBalanceClass::toMainUnit($value['materialId'], $value['num'], $value['unit']);
					insert([
						'table' => self::tableRecord,
						'field' => [
							'id'            => self::getNo(),
							'coid'          => self::$coid,
							'warehouseId'   => $value['warehouseId'],
							'materialId'    => $value['materialId'],
							'num'           => -1 * $mainUnitNum,
						],
					]);
				}
				$this->commitTrans();//提交事务
				auditingFollow(array(
					"type"   => "其他出库单",
					"typeId" => $info['id'],
					"text"   => "【{$this->control['name']}】确认",
				));
				//添加日志
				$type               = mb_substr($this->resp['warn'], 0, 2, 'utf-8');
				$text               = $this->control['name'] . $type . "了" . self::title . "id：【" . $id . '】';
				$this->resp['data'] = [
					'id'      => $info['id'],
					'orderNo' => $info['orderNo'],
				];
				$this->logText(["type" => self::page, "text" => $text]);
				//返回
				$this->code = 1;
			}
		}

		resp:
	}

	/**
	 * 删除
	 *
	 * @return void
	 */
	public function delete(): void
	{
		$array = $this->post('listId') ?? $this->post('id');
		if (!$this->power(self::page, "del")) {
			$this->resp['warn'] = "你没有删除的权限";
		} elseif (empty($array)) {
			$this->resp['warn'] = "你一个数据都没有选择呢";
		} else {
			$text  = "";
			$x     = 0;
			$array = is_array($array) ? $array : [$array];
			foreach ($array as $id) {
				$info = query(self::table, " id = '$id' ");
				if ($info['state'] == '已出库') {
					$warn = "删除失败：已出库，暂不能删除";
				} else {
					//最后删除基本参数
					delete(array("table" => self::table, "where" => " id = '$id' "));
					delete(array("table" => self::tableMx, "where" => " orderId = '$id' "));
					delete(array("table" => 'auditing_follow', "where" => " typeId = '$id' "));
					//返回
					$warn = "删除成功";
					$x++;
				}
				$text .= self::title . "ID【" . $info['id'] . "】" . $warn . "。<br>";
			}
			//添加日志
			$text = $this->control['name'] . "删除了" . self::title . "，结果如下：<br>" . $text;
			$this->logText(array("type" => self::page, "text" => $text));
			$this->resp['warn'] = "删除了" . $x . "个" . self::title . "，详情见系统日志。";
			$this->code         = 1;
		}
	}

	/**
	 * 详情
	 *
	 * @return void
	 */
	public function detail()
	{
		$id   = $this->post('id');
		$info = query(self::table, "id = '" . $id . "'");
		if (empty($id)) {
			$this->resp['warn'] = "ID为空";
		} elseif (empty($info['id'])) {
			$this->resp['warn'] = "未找到此" . self::title;
		} else {
			$target     = query(self::tableTarget, " khid = '$info[targetId]' ");
			$audit      = find([
				'table' => 'auditing_follow',
				'where' => " typeId = '$info[id]'",
			]);
			$result     = find([
				'table' => self::tableMx,
				'where' => " orderId = '$info[id]' order by time desc",
			]);
			$detail     = $outRecord = [];
			$totalMoney = 0;
			foreach ($result['array'] as $value) {
				$material    = query('material', " id = '$value[materialId]' ");
				$warehouse   = query('warehouse', " id = '$value[warehouseId]'");
				$rid         = self::generateId([$value['orderId'], $value['materialId']]);
				$temp        = find(['table' => 'auditing_follow', 'where' => "typeId = '$rid' AND type = '出库单' order by time desc"])['array'];
				$detail[]    = [
					'id'            => $value['id'],
					'materialId' => $value['materialId'],
					'code'          => $material['code'],
					'name'          => $material['name'],
					'mtype'         => $material['typeName'],
					'model'         => $material['model'],
					'unit'          => $material['unit'],
					'price'         => $value['price'],
					'text'          => $value['text'],
					'warehouse'     => $warehouse['name'],
					'warehouseId'   => $warehouse['id'],
					'orderNum'      => self::lostZero($value['orderNum'], 'numPrecision'),
					'num'           => self::lostZero($value['num'], 'numPrecision'),
					'rate'          => $value['rate'],
					'rateMoney'     => $value['num'] * $value['price'] * $value['rate'],
					'total'         => $value['num'] * $value['price'] * (1 + $value['rate']),
				];
				$totalMoney  += $value['num'] * $value['price'] * (1 + $value['rate']);
				if (!self::is_null_array($temp)) {
					$outRecord = array_merge($outRecord, $temp);
				}
			}
			$data['result'] = [
				'info'        => [
					"id"         => $info['id'],
					'staffName'  => self::findStaff($info['stid']),
					'orderNo'    => $info['orderNo'],
					'orderDate'  => $info['orderDate'],
					'type'       => $info['type'],
					'target'     => $target['companyName'] ?: '',
					'targetName' => $target['companyName'] ?: '',
					'targetId'   => $target['khid'] ?: '',
					"state"      => $info['state'],
					'text'       => $info['text'],
					'date'       => self::formatDate($info['time'], 'm/d'),
				],
				'detail'      => $detail,
				'outRecord'    => $outRecord ? self::my_sort($outRecord, 'time', SORT_DESC, SORT_STRING) : [],
				'auditRecord' => $audit['array'],
				'total'       => [
					'num'   => count($detail),
					'money' => $totalMoney,
				],
			];
			//返回
			$this->code         = 1;
			$this->resp['data'] = $data;
		}
	}


	/**
	 * 出库
	 */
	public function putOut()
	{
		$id   = $this->post('id');
		$num  = $this->post('num');
		$info = query(self::tableMx, " id = '$id'");
		$res  = query(self::table, " id = '$info[orderId]' ");
		if (!$this->power(self::page, 'edit')) {
			$this->resp['warn'] = '你还没有出库权限';
		} elseif (empty($res['id']) || empty($info['id'])) {
			$this->resp['warn'] = '未找到此出库单';
		} elseif (self::isNull($num)) {
			$this->resp['warn'] = '请填写数量';
		} elseif (!in_array($res['state'], ['待出库', '部分出库'])) {
			$this->resp['warn'] = '此出库单不是出库状态，不能出库';
		} elseif (abs($num) + $info['num'] > $info['orderNum']) {
			$this->resp['warn'] = '出库数量不能超过单据数量，你还可以出库' . ($info['orderNum'] - $info['num']);
		} else {
			$num = abs($num);
			$this->startTrans();
			$isPass             = false; // 事务通过标志
			$detailMoney        = ($info['num'] + $num) * $info['price'] * (1 + $info['rate']);
			$this->resp['warn'] = static::update([
				"table" => self::tableMx,
				"field" => [
					'num'   => $info['num'] + $num,
					'money' => $detailMoney,
				],
				"where" => "id = '$info[id]'",
			]);
			if (!in_array($this->resp['warn'], ["新增成功", "更新成功"])) {
				//回滚
				$this->rollback();
			} else {
				$isPass = true;
				if ($res['state'] == '待出库') {
					static::update([
						'table' => self::table,
						'field' => [
							'state'      => '部分出库',
							'commitTime' => $this->time,
						],
						'where' => " id = '{$res['id']}' ",
					]);
				}
				if ($isPass === true) {
					$mainUnitNum = inventoryBalanceClass::toMainUnit($info['materialId'], $num, $info['unit']);
					// 判断库存
					if (inventoryBalanceClass::inventoryNum($info['materialId'], $info['warehouseId']) - $mainUnitNum < 0) {
						$this->resp['warn'] = '出库数量不能大于库存数量';
						return;
					}
					insert([
						'table' => self::tableRecord,
						'field' => [
							'id'            => self::getNo(),
							'coid'          => self::$coid,
							'warehouseId'   => $info['warehouseId'],
							'materialId'    => $info['materialId'],
							'inventoryId'   => $info['orderId'],
							'inventoryMxId' => $info['id'],
							'num'           => -1 * $mainUnitNum,
						],
					]);
					// 关联表
					$targetDate = $targetNo = $targetText = $hiddenText = ' ';
					if ($res['sourceTable']) {
						$obj = query($res['sourceTable'], " id = '{$res['sourceId']}' ");
						if (!empty($obj['id'])) {
							$targetDate = $obj['recordDate'];
							$targetNo   = $obj['orderNo'];
							$targetText = $res['type'] . "单【{$obj['orderNo']}】";
							$hiddenText = $res['type'] . '单ID：' . $obj['id'] . '，出库单ID：' . $info['orderId'] . '出库单子ID：' . $info['id'];
						}
					}
					inventoryBalanceClass::insertRecord($res['targetId'], $res['type'], ($num * $info['price'] * (1 + $info['rate'])), self::tableMx, $info['id'], $targetDate, $targetNo, $targetText, $hiddenText);

					$material = query('material', " id = '$info[materialId]' ", 'code, name, model, unit');
					auditingFollow([
						"type"   => "出库单",
						"typeId" => self::generateId([$info['orderId'], $info['materialId']]),
						"text"   => "【{$this->control['name']}】通过【前端】出库【{$material['name']}-{$material['model']}】数量[$num]",
					]);
					$this->commitTrans();//提交事务
				}
				//添加日志
				$type = mb_substr($this->resp['warn'], 0, 2, 'utf-8');
				$text = $this->control['name'] . $type . "了" . self::title . "id：【" . $id . '】';
				$this->logText(["type" => self::page, "text" => $text]);
				$this->resp['data'] = $res['id'];
				$this->code         = 1;
			}
		}
		resp:
	}

	/**
	 * 确认出库
	 */
	public function done()
	{
		$id    = $this->post('id');
		$info  = query(self::table, " classify = 0 AND id = '$id'");
		$field = [
			'state'       => '已出库',
			'confirmTime' => $this->time,
		];
		if (!$this->power(self::page, 'edit')) {
			$this->resp['warn'] = '你还没有完成出库权限';
		} elseif (empty($info['id'])) {
			$this->resp['warn'] = '未找到此出库单';
		} elseif (!in_array($info['state'], ['待出库', '部分出库'])) {
			$this->resp['warn'] = '此出库单不是出库状态，不能出库';
		} else {
			$res = sqlFind(" SELECT IFNULL(SUM(orderNum), 0) as orderNum, IFNULL(SUM(num), 0) as num FROM " . self::tableMx . " WHERE orderId = '$info[id]' ");
			if ($res[0]['orderNum'] !== $res[0]['num']) {
				$this->resp['warn'] = '尚有部分物料未出库，无法出库完成';
				goto resp;
			}
			$this->resp['warn'] = update([
				"table" => self::table,
				"field" => $field,
				"where" => "id = '$info[id]'",
			]);
			if (in_array($this->resp['warn'], ["新增成功", "更新成功"])) {
				auditingFollow(array(
					"type"   => "出库单",
					"typeId" => $info['id'],
					"text"   => "【{$this->control['name']}】确认出库",
				));
				//添加日志
				$type = mb_substr($this->resp['warn'], 0, 2, 'utf-8');
				$text = $this->control['name'] . $type . "了" . self::title . "id：【" . $id . '】';
				$this->logText(["type" => self::page, "text" => $text]);
				$this->code = 1;
			}
		}

		resp:
	}

}


